<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="Content-Type" content="text/html"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Motors</title>

<style>
#MotorTable {
    position: center;
    background-image: url("background01.jpg");
    background-repeat: no-repeat;
    background-size: 400px;
    background-attachment: fixed;
}

.MotorInstance table {
    width: 200px;
    color: white;
    border-radius: 10%;

    /* background-color: rgba(255, 255, 255, 0.6); */
    /* background-color: rgba(255,165,0,0.3); */
    background-color: rgba(0,0,0,0.5);
}

.MotorInstance td {
    width: 60px;
}

.MotorInstance input[type="button"] {
    margin-left: 15%;
}

/* 平时隐藏，悬浮出现 */
input[type="range"] + span {
    display:none;
}
input[type="range"]:hover + span {
    display:inline;
}



</style>
</head>
<body>
<!-- Motor Div Template -->
<div class="MotorInstance">
    <table border="0">
        <tbody>
            <tr>
                <td>SpdFb</td><td>0</td>
            </tr>
            <tr>
                <td>PosFb</td><td>0</td>
            </tr>
            <tr>
                <td>SpdTar</td><td>0</td>
            </tr>
            <tr>
                <td>PosTar</td><td>0</td>
            </tr>
            <tr><td colspan="2">
                <form>
                    <input name="PosTarSet" type="range" min="-5" max="5" step="0.1" oninput="DispRangeValue(this)"/> <span name="PosTarSet">0</span><br/> 
                    <input name="SpdTarSet" type="range" min="-5" max="5" step="0.1" oninput="DispRangeValue(this)"/> <span name="SpdTarSet">0</span><br/>
                    <label>CtrlMod:</label>
                    <input name="CtrlMod" type="radio" value="2"> <label>Pos</label>
                    <input name="CtrlMod" type="radio" value="1" checked> <label>Spd</label>
                    <br />
                    <input type="button" value="发送" onclick="SendSettings(this)" >
                </form>
            </td></tr>
        </tbody>
    </table>
</div>

<table id="MotorTable" border="0">
    <tr><td id="CellM1"></td><td id="CellM2"></td></tr>
    <tr><td id="CellM3"></td><td id="CellM4"></td></tr>
</table>


<script>
// ========================================
//   Construct Page
// ========================================
var el_mx = document.getElementsByClassName("MotorInstance")[0]
var el_m1 = el_mx.cloneNode(true)
var el_m2 = el_mx.cloneNode(true)
var el_m3 = el_mx.cloneNode(true)
var el_m4 = el_mx.cloneNode(true)

el_mx.style.display = "none"
el_m1.getElementsByTagName("form")[0].setAttribute("name", "M1")
el_m2.getElementsByTagName("form")[0].setAttribute("name", "M2")
el_m3.getElementsByTagName("form")[0].setAttribute("name", "M3")
el_m4.getElementsByTagName("form")[0].setAttribute("name", "M4")

document.getElementById("CellM1").appendChild(el_m1)
document.getElementById("CellM2").appendChild(el_m2)
document.getElementById("CellM3").appendChild(el_m3)
document.getElementById("CellM4").appendChild(el_m4)


// ========================================
//   Global Variables and Settings
// ========================================
// ===== Request Data =====
const REQ_MB = BS([0x10, 0x03]);    // use modbus ws client

// websocket communicates to motor driver
var motor_ws = new WebSocket("ws://"+location.host);
// var motor_ws = new WebSocket("ws://192.168.4.1");

motor_ws.onopen = function(evt) {
    this.send(REQ_MB);  // protocol to notify server to create modbus ws client
    console.log("open ws")
}

motor_ws.onmessage = function(evt) {
    // console.log("ws recv: ", evt.data);

    // To display received data
    var json_str = evt.data
    json_str = json_str.replaceAll("(", "[").replaceAll(")", "]")
    json_data = JSON.parse(json_str)

    UpdateMotorInfo(document.getElementById("CellM1").childNodes[0], json_data[0])
    UpdateMotorInfo(document.getElementById("CellM2").childNodes[0], json_data[1])
    UpdateMotorInfo(document.getElementById("CellM3").childNodes[0], json_data[2])
    UpdateMotorInfo(document.getElementById("CellM4").childNodes[0], json_data[3])
}

motor_ws.onclose = function(evt) {
    console.log("close ws");
}

// Update received motor info
// The param is div element of motor instance
function UpdateMotorInfo(el, arr_info) {
    var lst_el_tr = el.getElementsByTagName("tr")
    for (var i = 0; i < 4; i++) {
        el_tr = lst_el_tr[i]
        el_td = el_tr.getElementsByTagName("td")[1]  // <td> to display value
        el_td.innerHTML = (arr_info[i] / 1000).toFixed(2)
    }
}

// Send form data about motor settings
function SendSettings(el) {
    var form = el.parentNode;
    console.log(form.name)
    var fdata = new FormData(form)
    
    // === assemble data to send ===
    // content of data: motor num, pos tar, spd tar, ctrl mod
    var data = new Array()
    data.push(form.name[1])
    // D3 format
    data.push(fdata.get("PosTarSet")* 1000) 
    data.push(fdata.get("SpdTarSet")* 1000) 
    data.push(fdata.get("CtrlMod"))
    console.log(data)
    console.log(JSON.stringify(data))
    motor_ws.send(JSON.stringify(data))
}

// Display range input's value in near element
function DispRangeValue(el) {
    var el_span = el.parentNode.querySelector('span[name="'+el.name+'"]')
    el_span.innerHTML = el.value
}


// ===== useful helpers =====
function BS(arr) {
    return new Uint8Array(arr);
}


</script>
</body>
</html>